package com.ruoyi.bookkeeping.service.impl;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.ruoyi.bookkeeping.domain.BookSort;
import com.ruoyi.bookkeeping.domain.param.AddBookAssetParam;
import com.ruoyi.bookkeeping.domain.param.GetBookAssetParam;
import com.ruoyi.bookkeeping.domain.param.HistogramVoParam;
import com.ruoyi.bookkeeping.domain.param.UpdateBookAssetParam;
import com.ruoyi.bookkeeping.domain.vo.*;
import com.ruoyi.bookkeeping.mapper.BookSortMapper;
import com.ruoyi.bookkeeping.util.DateUtil;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.bookkeeping.mapper.BookAssetMapper;
import com.ruoyi.bookkeeping.domain.BookAsset;
import com.ruoyi.bookkeeping.service.IBookAssetService;

/**
 * 收支Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-02-24
 */
@Service
public class BookAssetServiceImpl extends ServiceImpl<BookAssetMapper, BookAsset> implements IBookAssetService
{
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private BookSortMapper bookSortMapper;

    /**
     * 查询收支
     * 
     * @param assetId 收支主键bookSortService
     * @return 收支
     */
    @Override
    public BookAssetVo selectBookAssetByAssetId(Long assetId)
    {
        BookAssetVo bookAssetVo = new BookAssetVo();
        BookAsset bookAsset = baseMapper.selectById(assetId);
        if(ObjectUtil.isEmpty(bookAsset)){
            return bookAssetVo;
        }
        BeanUtils.copyProperties(bookAsset,bookAssetVo);
        return bookAssetVo;
    }

    /**
     * 查询收支列表
     * @param getBookAssetParam
     * @param userId
     * @return
     */
    @Override
    public List<BookAssetVo> selectBookAssetList(GetBookAssetParam getBookAssetParam, Long userId)
    {
        LambdaQueryWrapper<BookAsset> bookAssetLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bookAssetLambdaQueryWrapper.eq(BookAsset::getUserId,userId)
                .eq(StrUtil.isNotEmpty(getBookAssetParam.getAssetType()),BookAsset::getAssetType,getBookAssetParam.getAssetType())
                .eq(StrUtil.isNotEmpty(getBookAssetParam.getBillingType()),BookAsset::getBillingType,getBookAssetParam.getBillingType())
                .eq(!StrUtil.isBlankIfStr(getBookAssetParam.getSortId()),BookAsset::getSortId,getBookAssetParam.getSortId())
                .orderByDesc(true,BookAsset::getCreateTime);
        if(!StrUtil.isBlankIfStr(getBookAssetParam.getEndTime()) && !StrUtil.isBlankIfStr(getBookAssetParam.getStartTime())
                && StrUtil.isEmptyIfStr(getBookAssetParam.getMonthTime())){
            bookAssetLambdaQueryWrapper.ge(BookAsset::getCreateTime,getBookAssetParam.getStartTime());
            bookAssetLambdaQueryWrapper.le(BookAsset::getCreateTime,getBookAssetParam.getEndTime());
        }
        if(!StrUtil.isEmptyIfStr(getBookAssetParam.getMonthTime())){
            bookAssetLambdaQueryWrapper.between(StrUtil.isBlankIfStr(getBookAssetParam.getEndTime()) && StrUtil.isBlankIfStr(getBookAssetParam.getStartTime()),
                            BookAsset::getCreateTime,DateUtil.getOneDay(getBookAssetParam.getMonthTime()),DateUtil.getLastDay(getBookAssetParam.getMonthTime()));
        }

        List<BookAsset> bookAssets = baseMapper.selectList(bookAssetLambdaQueryWrapper);
        List<BookAssetVo> bookAssetVoList = new ArrayList<>();
        for(BookAsset bookAsset:bookAssets){
            BookAssetVo bookAssetVo = new BookAssetVo();
            BeanUtils.copyProperties(bookAsset,bookAssetVo);
            if(ObjectUtil.isNotEmpty(bookAsset.getSortId())){
                bookAssetVo.setSortName(bookSortMapper.selectById(bookAsset.getSortId()).getSortName());
            }
            bookAssetVoList.add(bookAssetVo);
        }
        return bookAssetVoList;
    }

    @Override
    public List<BookAsset> selectExportBookAssetList(GetBookAssetParam getBookAssetParam, Long userId) {
        LambdaQueryWrapper<BookAsset> bookAssetLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bookAssetLambdaQueryWrapper.eq(BookAsset::getUserId,userId)
                .eq(StrUtil.isNotEmpty(getBookAssetParam.getAssetType()),BookAsset::getAssetType,getBookAssetParam.getAssetType())
                .eq(StrUtil.isNotEmpty(getBookAssetParam.getBillingType()),BookAsset::getBillingType,getBookAssetParam.getBillingType())
                .eq(StrUtil.isBlankIfStr(getBookAssetParam.getSortId()),BookAsset::getSortId,getBookAssetParam.getSortId())
                .eq(StrUtil.isBlankIfStr(getBookAssetParam.getStartTime()),BookAsset::getCreateTime,getBookAssetParam.getStartTime())
                .between(StrUtil.isBlankIfStr(getBookAssetParam.getEndTime()) && StrUtil.isBlankIfStr(getBookAssetParam.getStartTime()),
                        BookAsset::getCreateTime,getBookAssetParam.getStartTime(),getBookAssetParam.getEndTime());
        return baseMapper.selectList(bookAssetLambdaQueryWrapper);
    }

    /**
     * 新增收支
     * @param addBookAssetParam
     * @param userId
     * @return
     */
    @Override
    public int insertBookAsset(AddBookAssetParam addBookAssetParam,Long userId)
    {
        BookAsset bookAsset = new BookAsset();
        BeanUtils.copyProperties(addBookAssetParam,bookAsset);
        if(ObjectUtil.isEmpty(addBookAssetParam.getCreateTime())){
            bookAsset.setCreateTime(DateUtils.getNowDate());
        }else {
            bookAsset.setCreateTime(addBookAssetParam.getCreateTime());
        }
        bookAsset.setUserId(userId);
        bookAsset.setDelFlag("0");
        bookAsset.setCreateBy(sysUserMapper.selectUserById(userId).getUserName());
        return baseMapper.insert(bookAsset);
    }

    /**
     * 修改收支
     * @param updateBookAssetParam
     * @param userId
     * @return
     */
    @Override
    public int updateBookAsset(UpdateBookAssetParam updateBookAssetParam,Long userId)
    {
        if(!ObjectUtil.equal(userId,baseMapper.selectById(updateBookAssetParam.getAssetId()).getUserId())){
            return 0;
        }
        LambdaQueryWrapper<BookAsset> bookAssetLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bookAssetLambdaQueryWrapper.eq(BookAsset::getAssetId,updateBookAssetParam.getAssetId())
                        .eq(BookAsset::getUserId,userId);
        BookAsset bookAsset = baseMapper.selectOne(bookAssetLambdaQueryWrapper);
        BeanUtils.copyProperties(updateBookAssetParam,bookAsset);
        bookAsset.setUpdateTime(DateUtils.getNowDate());
        bookAsset.setUpdateBy(sysUserMapper.selectUserById(userId).getUserName());
        if(!ObjectUtil.isEmpty(updateBookAssetParam.getCreateTime())){
            bookAsset.setCreateTime(updateBookAssetParam.getCreateTime());
        }
        return baseMapper.updateById(bookAsset);
    }

    /**
     * 批量删除收支
     * 
     * @param assetIds 需要删除的收支主键
     * @return 结果
     */
    @Override
    public int deleteBookAssetByAssetIds(Long[] assetIds,Long userId)
    {
        for (Long id : assetIds) {
            LambdaUpdateWrapper<BookAsset> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(BookAsset::getAssetId,id)
                    .eq(BookAsset::getUserId,userId);
            if(!ObjectUtil.equal(userId,baseMapper.selectById(id).getUserId())){
                return 0;
            }
        }
        return baseMapper.deleteBatchIds(Arrays.asList(assetIds));
    }

    @Override
    public PieVoList pie(Date date, Long userId) {
        PieVoList pieVoLists = new PieVoList();
        pieVoLists.setInPieVos(selectByMonth(userId,date,"0"));
        pieVoLists.setPayPieVos(selectByMonth(userId,date,"1"));
        return pieVoLists;
    }
    private List<PieVo> selectByMonth(Long userId,Date date,String assetType){
        String format = new SimpleDateFormat("yyyy-MM").format(date);
        MPJLambdaWrapper<BookAsset> pay = new MPJLambdaWrapper<>();
        pay.selectSum(BookAsset::getAmount)
                .select(BookAsset::getAssetType,BookAsset::getSortId)
                .leftJoin(BookSort.class,BookSort::getSortId,BookAsset::getSortId)
                .select(BookSort::getSortName)
                .eq(BookAsset::getUserId,userId)
                .eq(BookAsset::getAssetType,assetType)
                .likeRight(BookAsset::getCreateTime,format)
                .groupBy(BookAsset::getSortId);
        return baseMapper.selectJoinList(PieVo.class, pay);
    }

    @Override
    public List<PieVo> progressComparison(Date date, Long userId) {
        return selectByMonth(userId,date,"1");
    }

    @Override
    public List<HistogramListVo> histogram(Long userId){
        List<HistogramListVo> histogramListVos = new ArrayList<>();
        String format = new SimpleDateFormat("yyyy-MM").format(new Date());
        List<String> strings = DateUtil.getSixMonth(format);
        for(String s:strings){
            HistogramListVo histogramListVo = new HistogramListVo();
            MPJLambdaWrapper<BookAsset> in = new MPJLambdaWrapper<>();
            in.eq(BookAsset::getUserId,userId)
                    .eq(BookAsset::getAssetType,"0")
                    .likeRight(BookAsset::getCreateTime,s)
                    .selectSum(BookAsset::getAmount)
                    .select(BookAsset::getAssetType,BookAsset::getCreateTime)
                    .leftJoin(BookSort.class,BookSort::getSortId,BookAsset::getSortId);
            if(ObjectUtil.isEmpty(baseMapper.selectJoinOne(HistogramVo.class, in))){
                HistogramVo histogramVo = new HistogramVo();
                histogramVo.setAssetType("0");
                histogramVo.setAmount(0.0);
                histogramVo.setCreateTime(s);
                histogramListVo.setInHistogramListVo(histogramVo);
            }else {
                histogramListVo.setInHistogramListVo(baseMapper.selectJoinOne(HistogramVo.class, in));
            }
            MPJLambdaWrapper<BookAsset> pay = new MPJLambdaWrapper<>();
            pay.eq(BookAsset::getUserId,userId)
                    .eq(BookAsset::getAssetType,"1")
                    .likeRight(BookAsset::getCreateTime,s)
                    .selectSum(BookAsset::getAmount)
                    .select(BookAsset::getAssetType,BookAsset::getCreateTime)
                    .leftJoin(BookSort.class,BookSort::getSortId,BookAsset::getSortId);
            if(ObjectUtil.isEmpty(baseMapper.selectJoinOne(HistogramVo.class, pay))){
                HistogramVo histogramVo1 = new HistogramVo();
                histogramVo1.setAssetType("1");
                histogramVo1.setAmount(0.0);
                histogramVo1.setCreateTime(s);
                histogramListVo.setPayHistogramListVo(histogramVo1);
            }else {
                histogramListVo.setPayHistogramListVo(baseMapper.selectJoinOne(HistogramVo.class, pay));
            }
                histogramListVos.add(histogramListVo);
        }
        return histogramListVos;
    }

    @Override
    public List<BookAssetListVo> monthMaxAndMin(Long userId) {
        List<BookAssetListVo> bookAssetVoList = new ArrayList<>();
        String format = new SimpleDateFormat("yyyy-MM").format(new Date());
        List<String> strings = DateUtil.getSixMonth(format);
        for(String s:strings){
            BookAssetListVo bookAssetVo = new BookAssetListVo();
            MPJLambdaWrapper<BookAsset> max = new MPJLambdaWrapper<>();
            max.eq(BookAsset::getUserId,userId)
                    .eq(BookAsset::getAssetType,"0")
                    .selectMax(BookAsset::getAmount)
                    .likeRight(BookAsset::getCreateTime,s)
                    .select(BookAsset::getCreateTime,BookAsset::getBillingType,BookAsset::getAssetId,BookAsset::getRemark)
                    .leftJoin(BookSort.class,BookSort::getSortId,BookAsset::getSortId)
                    .select(BookSort::getSortName);
            bookAssetVo.setBookAssetMaxVo(baseMapper.selectJoinOne(BookAssetMaxMinVo.class,max));
            MPJLambdaWrapper<BookAsset> min = new MPJLambdaWrapper<>();
            min.eq(BookAsset::getUserId,userId)
                    .eq(BookAsset::getAssetType,"0")
                    .selectMin(BookAsset::getAmount)
                    .likeRight(BookAsset::getCreateTime,s)
                    .select(BookAsset::getCreateTime,BookAsset::getBillingType,BookAsset::getAssetId,BookAsset::getRemark)
                    .leftJoin(BookSort.class,BookSort::getSortId,BookAsset::getSortId)
                    .select(BookSort::getSortName);
            bookAssetVo.setBookAssetMinVo(baseMapper.selectJoinOne(BookAssetMaxMinVo.class,min));
            if(!ObjectUtil.isNull(bookAssetVo.getBookAssetMaxVo()) && !ObjectUtil.isNull(bookAssetVo.getBookAssetMinVo())){
                bookAssetVoList.add(bookAssetVo);
            }
        }
        return bookAssetVoList;
    }
}
